package com.grad.why.studentsystem.service.impl;

import com.grad.why.studentsystem.domain.*;
import com.grad.why.studentsystem.domain.current.CurrentCourseArrangeInfo;
import com.grad.why.studentsystem.mapper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Priority;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: 创建线程任务服务
 * @ClassName: CustomMultiThreadingService
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午3:17:57
 */
@Service
public class CustomMultiThreadingService {
    private Logger logger = LoggerFactory.getLogger(CustomMultiThreadingService.class);

    @Autowired
    private OptionparamsMapper optionparamsMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private ChooseCourseMapper chooseCourseMapper;

    @Autowired
    private CourseArrangeMapper courseArrangeMapper;

    @Autowired
    private RuntimecoursearrangeinfoMapper runtimecoursearrangeinfoMapper;

    @Autowired
    private CameraMapper cameraMapper;

    @Autowired
    private RuntimecoursearrangeinfodetailMapper runtimecoursearrangeinfodetailMapper;

    @Autowired
    private RuntimecoursearrangeinforecordMapper runtimecoursearrangeinforecordMapper;

    @Autowired
    private KillinfosMapper killinfosMapper;

    @Autowired
    private StudentarrivedinfoMapper studentarrivedinfoMapper;

    /**
     * @Description:通过@Async注解表明该方法是一个异步方法，
     * 如果注解在类级别上，则表明该类所有的方法都是异步方法，而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     * @Title: executeAysncTask1
     * @Date: 2018年9月21日 下午2:54:32
     * @Author: OnlyMate
     * @Throws
     */
    @Async
    public void initCourseInfos() throws Exception {
        while(true){
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String startDate = optionparamsMapper.getParamValueByParamName("startdate");

            Date parseStartDate = sdf.parse(startDate);

            int days = differentDays(parseStartDate,date);
            int thisWeek = days/7;

            if(days%7 > 0){
                thisWeek = thisWeek + 1;
            }

            //更新当前周数
            int n = optionparamsMapper.updateThisWeek(String.valueOf(thisWeek));

            //获取从未结课到结课的课程信息
            List<Course> shouldUpdateCourseList = courseMapper.getShouldUpdateCourseList(thisWeek);
            for(int i = 0;i<shouldUpdateCourseList.size();i++){
                if(shouldUpdateCourseList.get(i).getCourseteacher() == null){
                    continue;
                }
                Course currntCourseInfo = shouldUpdateCourseList.get(i);
                currntCourseInfo.setCoursestate("结课");
                int cid = currntCourseInfo.getCourseid();
                courseMapper.updateByPrimaryKey(currntCourseInfo);
                List<ChooseCourse> chooseCourses = chooseCourseMapper.getChooseCourseByCid(cid);
                for(int j = 0;j<chooseCourses.size();j++){
                    ChooseCourse chooseCourse = chooseCourses.get(j);
                    chooseCourse.setState("结课");
                    chooseCourseMapper.updateByPrimaryKeySelective(chooseCourse);
                }
            }


            //获取需要从未开课到未结课的课程信息
            List<Course> shouldUpdateCourseListOfNoStart = courseMapper.getshouldUpdateCourseListOfNoStartList(thisWeek);
            for(int i = 0;i<shouldUpdateCourseListOfNoStart.size();i++){
                if(shouldUpdateCourseListOfNoStart.get(i).getCourseteacher() == null){
                    continue;
                }
                Course currentCourseInfo = shouldUpdateCourseListOfNoStart.get(i);
                currentCourseInfo.setCoursestate("未结课");
                courseMapper.updateByPrimaryKey(currentCourseInfo);
                int cid = currentCourseInfo.getCourseid();
                List<ChooseCourse> chooseCourses = chooseCourseMapper.getChooseCourseByCid(cid);
                for(int j = 0;j<chooseCourses.size();j++){
                    ChooseCourse chooseCourse = chooseCourses.get(j);
                    chooseCourse.setState("未结课");
                    chooseCourseMapper.updateByPrimaryKeySelective(chooseCourse);
                }
            }

            //设置从未结课、结课到未开课的课程安排信息
            List<Course> shouldUpdateCourseInfoOfChangeNoStart = courseMapper.getshouldUpdateCourseInfoOfChangeNoStart(thisWeek);
            for(int i = 0;i<shouldUpdateCourseInfoOfChangeNoStart.size();i++){
                if(shouldUpdateCourseInfoOfChangeNoStart.get(i).getCourseteacher() == null){
                    continue;
                }
                Course currentCourse = shouldUpdateCourseInfoOfChangeNoStart.get(i);
                currentCourse.setCoursestate("未开课");
                courseMapper.updateByPrimaryKey(currentCourse);
                int cid = currentCourse.getCourseid();
                List<ChooseCourse> chooseCourses = chooseCourseMapper.getChooseCourseByCid(cid);
                for(int j = 0;j<chooseCourses.size();j++){
                    ChooseCourse currentChooseCourse =  chooseCourses.get(j);
                    currentChooseCourse.setState("未开课");
                    chooseCourseMapper.updateByPrimaryKeySelective(currentChooseCourse);
                }
            }



            //30分钟执行一次
            Thread.sleep(1000 * 60 * 30);
        }
    }

    /**
     * @Description:通过@Async注解表明该方法是一个异步方法，
     * 如果注解在类级别上，则表明该类所有的方法都是异步方法，而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     * @Title: executeAsyncTask2
     * @Date: 2018年9月21日 下午2:55:04
     * @Author: OnlyMate
     * @Throws
     */
    @Async
    public void getRunningCourseAndCourseArrangeInfos() throws InterruptedException {
        while(true){

            //当前周
            int thisweek = Integer.parseInt(optionparamsMapper.getParamValueByParamName("thisweek"));

            //获取正在教学的课程
            List<Course> courses = courseMapper.getRunningCourseInfoByThisWeek(thisweek);

            //所有课程的课程安排信息
            List<List<CurrentCourseArrangeInfo>> courseArrangeinfos = new ArrayList<>();
            for(int i = 0;i<courses.size();i++){
                //每一门课程的具体时间、教室安排
                List<CurrentCourseArrangeInfo> courseArranges = courseArrangeMapper.getCourseArrangeInfoByCid(courses.get(i).getCourseid());
                for(int j = 0;j<courseArranges.size();j++){

                    //添加学生信息到课程安排信息之中
                    List<Student> stuInfos = chooseCourseMapper.getStudentByCourseId(courseArranges.get(j).getCid());
                    StringBuffer sb = new StringBuffer("");
                    int stuLength = stuInfos.size();
                    for(int k = 0;k<stuLength;k++){
                        if(k == stuLength - 1){
                            sb.append(stuInfos.get(k).getName());
                        }else if(k<stuLength-1){
                            sb.append(stuInfos.get(k).getName()+",");
                        }
                    }
                    //设置课程名单
                    courseArranges.get(j).setShouldnamelabels(sb.toString());

                    //设置课程应到人数
                    courseArranges.get(j).setShouldcount(stuLength);
                }
                courseArrangeinfos.add(courseArranges);
            }

            List<CurrentCourseArrangeInfo> needRecordCourseArrangeInfo = new ArrayList<CurrentCourseArrangeInfo>();

            //设置当天的日期类
            Date today = new Date();
            String now = today.getHours()+":"+today.getMinutes()+":"+today.getSeconds();

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(today);
            String weekday = getWeekDay(calendar.get(Calendar.DAY_OF_WEEK) - 1);

            for(int i = 0;i<courseArrangeinfos.size();i++){
                List<CurrentCourseArrangeInfo> handleCourseArrangeInfos = courseArrangeinfos.get(i);
                for(int j = 0;j<handleCourseArrangeInfos.size();j++){
                    if(weekday.equals(handleCourseArrangeInfos.get(j).getWeekday())){
                        String[] startEndTimes = getStartAndEndTime(handleCourseArrangeInfos.get(j).getCourseindex());
                        if(compareTimes(startEndTimes[0],now)&&compareTimes(now,startEndTimes[1])){
                            needRecordCourseArrangeInfo.add(handleCourseArrangeInfos.get(j));
                        }
                    }
                }
            }

            List<Runtimecoursearrangeinfo> runtimeCourseArrangeInfos = runtimecoursearrangeinfoMapper.getAllRuntimeCourseInfos();

            //逻辑问题
            for(int i = 0;i<runtimeCourseArrangeInfos.size();i++){
                Runtimecoursearrangeinfo r = runtimeCourseArrangeInfos.get(i);
                if(!RuntimeCourseInfoIsExist(needRecordCourseArrangeInfo,r)){
                    //删除当前未在正在进行的课程中的课程安排信息
                    int n = runtimecoursearrangeinfoMapper.dropRuntimeCourseInfoByCourseArrangeId(r.getCoursearrangeid());

                    //检查detail中是否存在应该删除的课程安排信息
                    if(runtimecoursearrangeinfodetailMapper.checkCurrentCourseInfoExistByCourseArrangeId(r.getCoursearrangeid()) > 0){
                        Runtimecoursearrangeinfodetail runtimecoursearrangeinfodetail = runtimecoursearrangeinfodetailMapper.selectByPrimaryKey(r.getCoursearrangeid());
                        Runtimecoursearrangeinforecord runtimecoursearrangeinforecord = new Runtimecoursearrangeinforecord(runtimecoursearrangeinfodetail);
                        runtimecoursearrangeinforecordMapper.insertSelective(runtimecoursearrangeinforecord);

                        String realStudentNamelabel = runtimecoursearrangeinforecord.getRealnamelabels();
                        String shouldStudentNamelabel = runtimecoursearrangeinforecord.getShouldnamelabels();

                        String[] shouldStudentNamelabels = shouldStudentNamelabel.split(",");
                        String[] realStudentNameLabels = realStudentNamelabel.split("\\|");

                        ArrayList<String> realStudentNameLabelList = new ArrayList<>();

                        for(int j = 0;j<realStudentNameLabels.length;j++){
                            realStudentNameLabelList.add(realStudentNameLabels[j]);
                        }

                        for(int j = 0;j<shouldStudentNamelabels.length;j++){
                            Studentarrivedinfo studentarrivedinfo = new Studentarrivedinfo();
                            studentarrivedinfo.setRecordid(runtimecoursearrangeinforecordMapper.getMaxId());
                            String[] stuInfos = shouldStudentNamelabels[j].split("_");
                            studentarrivedinfo.setStudentid(Integer.parseInt(stuInfos[0]));
                            studentarrivedinfo.setStudentname(stuInfos[1]);
                            if(!realStudentNameLabelList.contains(shouldStudentNamelabels[j])){
                                studentarrivedinfo.setState(0);
                            }else{
                                studentarrivedinfo.setState(1);
                            }
                            studentarrivedinfoMapper.insertSelective(studentarrivedinfo);
                        }

                        runtimecoursearrangeinfodetailMapper.deleteByPrimaryKey(runtimecoursearrangeinfodetail.getCoursearrangeid());


                        Killinfos killinfos = killinfosMapper.selectByPrimaryKey(r.getCoursearrangeid());
                        if(killinfos!=null) {
                            killinfos.setShouldkill(1);
                            killinfosMapper.updateByPrimaryKeySelective(killinfos);
                        }
                    }
                }
            }

            for(int i = 0;i<needRecordCourseArrangeInfo.size();i++){
                List<Student> stuInfos = chooseCourseMapper.getStudentByCourseId(needRecordCourseArrangeInfo.get(i).getCid());
                StringBuffer sb = new StringBuffer("");
                int stuLength = stuInfos.size();
                for(int j = 0;j<stuLength;j++){
                    Student stu = stuInfos.get(j);
                    sb.append(stu.getId()+"_"+stu.getName()+",");
                }
                String studentList = sb.toString();

                needRecordCourseArrangeInfo.get(i).setShouldnamelabels(sb.toString().substring(0,studentList.length() - 1));
                needRecordCourseArrangeInfo.get(i).setShouldcount(stuLength);
            }

            if(needRecordCourseArrangeInfo.size() > 0){
                for(int i = 0;i<needRecordCourseArrangeInfo.size();i++){
                    Integer coursearrangeid = needRecordCourseArrangeInfo.get(i).getCoursearrangeid();
                    int rows = runtimecoursearrangeinfoMapper.checkIsExist(coursearrangeid);
                    if(rows>0){
                        runtimecoursearrangeinfoMapper.updateByPrimaryKeySelective(new Runtimecoursearrangeinfo(needRecordCourseArrangeInfo.get(i)));
                    }else{
                        Runtimecoursearrangeinfo runtimecoursearrangeinfo = new Runtimecoursearrangeinfo(needRecordCourseArrangeInfo.get(i));
                        runtimecoursearrangeinfoMapper.insertSelective(runtimecoursearrangeinfo);
                        int exist = runtimecoursearrangeinfodetailMapper.checkCourseArrangeInfoExist(runtimecoursearrangeinfo.getCoursearrangeid());
                        if(exist == 0){
                            runtimecoursearrangeinfodetailMapper.insertSelective(new Runtimecoursearrangeinfodetail(runtimecoursearrangeinfo));

                            int n = killinfosMapper.getExistKillInfos(runtimecoursearrangeinfo.getCoursearrangeid());

                            if(n>0){
                                killinfosMapper.updateByPrimaryKeySelective(new Killinfos(runtimecoursearrangeinfo.getCoursearrangeid()));
                            }else{
                                killinfosMapper.insertSelective(new Killinfos(runtimecoursearrangeinfo.getCoursearrangeid()));
                            }
                        }
                    }
                }
            }

            int n = optionparamsMapper.updateRuntimeCount(String.valueOf(needRecordCourseArrangeInfo.size()));

            Thread.sleep(15*1000);
        }
    }

    private boolean RuntimeCourseInfoIsExist(List<CurrentCourseArrangeInfo> needRecordCourseArrangeInfo, Runtimecoursearrangeinfo r) {

       for(int i = 0;i<needRecordCourseArrangeInfo.size();i++){
                if(needRecordCourseArrangeInfo.get(i).getCoursearrangeid() == r.getCoursearrangeid()){
                    return true;
                }
       }
       return false;
    }

    @Async
    public void accordingClassRoomIdGetCameraId(int coursearrangeid,Camera camera) throws InterruptedException, IOException {
            String courseid = String.valueOf(courseArrangeMapper.getCourseIdByCourseaArrangeId(coursearrangeid));
            String cameraId = camera.getCameraid().toString();

            //获取对应摄像头的图像
            String[] argsArray = new String[] {"python", "D:\\git\\face_recognition-master\\face_recognition-master\\mytest\\cvCaptureDemo"+cameraId+".py",courseid,String.valueOf(coursearrangeid),cameraId};
            Process pr = Runtime.getRuntime().exec(argsArray);
            BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
            String line;
            boolean flag = true;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
            in.close();
    }

    /**
     * date2比date1多的天数
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDays(Date date1,Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2)   //同一年
        {
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++)
            {
                if(i%4==0 && i%100!=0 || i%400==0)    //闰年
                {
                    timeDistance += 366;
                }
                else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2-day1) ;
        }
        else    //不同年
        {
            return day2-day1;
        }
    }

    /**
     * 返回工作日
     * @param index
     * @return
     */
    public static String getWeekDay(int index){
        String[] weekdays = new String[]{"星期五","星期一","星期二","星期三","星期四","星期五","星期六"};
        return weekdays[index];
    }

    /**
     * 上课时间判断
     * @param courseIndex
     * @return
     */
    public static String[] getStartAndEndTime(String courseIndex){
        String[] times = new String[2];
        if(courseIndex.equals("第一大节")){
            times[0] = "08:20:00";
            times[1] = "23:59:00";
        }else if(courseIndex.equals("第二大节")){
            times[0] = "10:20:00";
            times[1] = "12:00:00";
        }else if(courseIndex.equals("第三大节")){
            times[0] = "14:00:00";
            times[1] = "15:40:00";
        }else if(courseIndex.equals("第四大节")){
            times[0] = "16:00:00";
            times[1] = "23:59:00";
        }else if(courseIndex.equals("第五大节")){
            times[0] = "19:00:00";
            times[1] = "20:40:00";
        }
        return times;
    }

    public static boolean compareTimes(String startTime,String endTime){
        String[] startTimeinfos = startTime.split(":");
        String[] endTimeinfos = endTime.split(":");
        if(Integer.parseInt(startTimeinfos[0]) < Integer.parseInt(endTimeinfos[0])){
            return true;
        }else if(Integer.parseInt(startTimeinfos[0]) == Integer.parseInt(endTimeinfos[0])){
            if(Integer.parseInt(startTimeinfos[1]) < Integer.parseInt(endTimeinfos[1])){
                return true;
            }else if(Integer.parseInt(startTimeinfos[1]) == Integer.parseInt(endTimeinfos[1])){
                if(Integer.parseInt(startTimeinfos[2]) <= Integer.parseInt(endTimeinfos[2])){
                    return true;
                }
            }
        }
        return false;
    }


}